home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: MegaDisc / MegaDisc 30 (1992-10)(MegaDisc Digital Publishing)(AU)(Disk 1 of 2)[WB].zip / MegaDisc 30 (1992-10)(MegaDisc Digital Publishing)(AU)(Disk 1 of 2)[WB].adf / Programs / WeekDay / date.c next >
C/C++ Source or Header  |  1992-10-05  |  10KB  |  387 lines

  1. /****************************************************************************
  2. *$RevHead_Start                                                             *
  3. *                                                                           *
  4. * Project Details                                                           *
  5. * ---------------                                                           *
  6. * Project Name:    WeekDay                                                  *
  7. * Project Version: 0.8                                                      *
  8. * Copyright:       © David M. Balean 1992                                   *
  9. * Date:            Monday 17th August 1992                                  *
  10. * Start DateStamp: 13-Aug-1992 11.51.25.30                                  *
  11. * Project Manager: DMB, 44 Wyong Rd, Killarney Vale, NSW 2261               *
  12. *                                                                           *
  13. *****************************************************************************
  14. *                                                                           *
  15. * This File:       date.c                                                   *
  16. *$Author:          David M. Balean                                          *
  17. *$File Version:    0.7                                                      *
  18. *$DateStamp:       16-Aug-1992 21.40.55.39                                  *
  19. *                                                                           *
  20. *****************************************************************************
  21. * File Summary:                                                             *
  22. * Calculate the day of the week from a given date.                          *
  23. *****************************************************************************
  24. *                                                                           *
  25. * Date        Time         Version Author                                   *
  26. *                                                                           *
  27. * 13-Aug-1992 11.47.41.22  0.5     David M. Balean                          *
  28. *                                                                           *
  29. * 13-Aug-1992 13.11.26.47  0.6     David M. Balean                          *
  30. * Added check for legal date - allows from 5 AD onwards.                    *
  31. *                                                                           *
  32. * 16-Aug-1992 21.40.55.39  0.7     David M. Balean                          *
  33. * Now uses an array of sums of days in the months of the year.              *
  34. * Add a day if leap year and after February.                                *
  35. * Could use Gauss's method: (c=centuries, y=tens and units m=month d=day)   *
  36. *        A = int[2.6m - .2] + d + y + int[y/4] + int[c/4] - 2c              *
  37. * but then if month is Jan or Feb it is part of previous year.(then % 7 )   *
  38. *                                                                           *
  39. *$RevHead_End                                                               *
  40. ****************************************************************************/
  41.  
  42. #include <exec/types.h>
  43.  
  44. /* This define is in intuition/intuition.h */
  45. #define FOREVER for(;;)
  46.  
  47.  
  48. /**************************************************************************
  49. A year divisible by 4 is a leap year unless it is divisible by 100, except
  50. that a year divisible by 400 is a leap year.
  51. This means that the year 2000 is a leap year because it is divisible by 400.
  52.  
  53.     if (year % 4 == 0   &&  year % 100 != 0  ||  year % 400 == 0)
  54.         THEN IT IS LEAP YEAR !!!
  55. Therefore:
  56. ***************************************************************************/
  57.  
  58. /* Leap year in Gregorian calendar */
  59. #define GLEAPYEAR(year)  ( (!(year % 4) && (year % 100)) || !(year % 400) )
  60.  
  61. /***************************************************************************
  62. In the Julian calendar, if a year is divisible by 4 then it is a leap year.
  63. The Julian calendar was used up to 4th October 1582.  Then 11 days
  64. were skipped and the next day was 15th October.  The Gregorian
  65. calendar has been used from then on in most RC countries.  Britain
  66. changed in 1752 when 2-9-1752 was followed by 14-9-1752 and there was
  67. rioting because the workers wanted to be paid for their lost days! 
  68. ***************************************************************************/
  69.  
  70. /* Leap year in Julian calendar */
  71. #define JLEAPYEAR(year) ( !(year % 4))
  72.  
  73.  
  74. static int MonthDays[] =
  75.     {
  76.     31,
  77.     28,
  78.     31,
  79.     30,
  80.     31,
  81.     30,
  82.     31,
  83.     31,
  84.     30,
  85.     31,
  86.     30,
  87.     31
  88.     };
  89.  
  90.  
  91. /* The sums of the days in the months up to (month - 1). Could be made % 7 */
  92.  
  93. static WORD MonthSum[] =
  94.     {
  95.     0,
  96.     31,
  97.     59,
  98.     90,
  99.     120,
  100.     151,
  101.     181,
  102.     212,
  103.     243,
  104.     273,
  105.     304,
  106.     334
  107.     };
  108.  
  109.  
  110. static UBYTE *WeekDay[] =
  111.     {
  112.  
  113.     "Sunday",
  114.  
  115.     "Monday",
  116.  
  117.     "Tuesday",
  118.  
  119.     "Wednesday",
  120.  
  121.     "Thursday",
  122.  
  123.     "Friday",
  124.  
  125.     "Saturday",
  126.  
  127.     "ILLEGAL"
  128.     };
  129.  
  130.  
  131.  
  132. /********************************
  133.  * CompareDate(d1,d2)        *
  134.  * Compare date1 with date2.    *
  135.  * Return:            *
  136.  *    0    if identical    *
  137.  *     1    if d2 later     *
  138.  *    -1    if d2 earlier    *
  139.  ********************************/
  140.  
  141.  
  142. int CompareDate(d1,m1,y1,d2,m2,y2)
  143.  
  144. int d1,m1,y1,d2,m2,y2;
  145.  
  146. {
  147. register int r;
  148.  
  149.  
  150. if (y1 < y2)        r = 1;
  151. else if (y1 > y2)    r = -1;
  152. else if (m1 < m2)    r = 1;
  153. else if (m1 > m2)    r = -1;
  154. else if ( d1 < d2)    r = 1;
  155. else if ( d1 > d2)    r = -1;
  156. else r = 0;
  157.  
  158. return(r);
  159. }
  160.  
  161.  
  162. /****************************************
  163.  * BOOL jLegalDate(d)            *
  164.  * Return TRUE if struct Date *d is    *
  165.  * a legal date, otherwise FALSE.    *
  166.  * Also corrects MonthDays for leap year*
  167.  ****************************************/
  168.  
  169. BOOL jLegalDate(d,m,y)
  170.  
  171. int    d,m,y;
  172.  
  173. {
  174.  
  175. /* Julian */
  176. if (y >= 5 )
  177.     {
  178.     if (JLEAPYEAR(y))
  179.         MonthDays[1] = 29;
  180.     else
  181.         MonthDays[1] = 28;
  182.  
  183.     if ((m >= 1) && (m <= 12))
  184.         if ((d >= 1) && (d <= MonthDays[m-1]))
  185.             return(TRUE);
  186.     }
  187.  
  188. return(FALSE);
  189.  
  190. }
  191.  
  192. /****************************************
  193.  * BOOL gLegalDate(d)            *
  194.  * Return TRUE if struct Date *d is    *
  195.  * a legal date, otherwise FALSE.    *
  196.  * Also corrects MonthDays for leap year*
  197.  ****************************************/
  198.  
  199. BOOL gLegalDate(d,m,y)
  200.  
  201. int    d,m,y;
  202.  
  203. {
  204.  
  205. /* Gregorian */
  206. if (CompareDate(d,m,y,15,10,1582) <= 0)
  207.     {
  208.     if (GLEAPYEAR(y))
  209.         MonthDays[1] = 29;
  210.     else
  211.         MonthDays[1] = 28;
  212.  
  213.     if ((m >= 1) && (m <= 12))
  214.         if ((d >= 1) && (d <= MonthDays[m-1]))
  215.             return(TRUE);
  216.     }
  217.  
  218. return(FALSE);
  219. }
  220.  
  221.  
  222.  
  223.  
  224. /***********************************************************************
  225.  * Algorithm (Gregorian):
  226.  * Using the year of previous year:-
  227.  * Get number of 400 year cycles since 1 AD (not actually so in fact...).
  228.  * Convert to days, K1 = 146097 days in 400 year cycle.
  229.  * From what's left get number of 4 year cycles.
  230.  * Convert to days, K2 = 1461 days in 4 year cycle.
  231.  * From what's left after that get number of years (maximum = 7,
  232.  *    previous year was a leap year)
  233.  * Convert to days.
  234.  * Calculate number of days to this day in this year.
  235.  * Add all the days up to make the total number of days.
  236.  * There may be a correction constant to add to make it give 0 as Sunday.
  237.  * Use %7 to get the day of the week.
  238.  * This may seem long winded, but it should always give the right answer
  239.  * if on or after 15th October 1582 when the N.S. calendar started.
  240.  * What about earlier?
  241.  **********************************************************************/
  242.  
  243. ULONG gCalculate(day,month,year)
  244.  
  245. LONG    day, month, year;
  246.  
  247. {
  248. REGISTER ULONG    y, days;
  249.  
  250.  
  251. /* If this is the Gregorian calendar... */
  252.  
  253.  
  254.  
  255. /************************************************************************
  256.  * For the Gregorian calendar:-                        *
  257.  * c400 = y / 400;    Number of 400 year cycles from year 1        *
  258.  * c400 * K1 = Number of days so far                    *
  259.  * y %= 400;        Remainder                    *
  260.  * c4 = y / 4;        Number of 4 year cycles, add c4 * K2 to days    *
  261.  * h = y / 100;        Number of 'hundreds' which are NOT leap years    *
  262.  * y = (y % 400) % 4;    Remainder                    *
  263.  * Now up to maximum of 7 more years                    *
  264.  * if (y)    days += (365 * y) + 1;    - not sure about leap years    *
  265.  * days += day + Constant;                        *
  266.  * There has to be a way af calculating the month days instead of    *
  267.  * adding them up.....                            *
  268.  * I've left the code in such a manner that I can understand it.    *
  269.  * It can be greatly simplified.                    *
  270.  ************************************************************************/
  271.  
  272.  
  273.  
  274. y = year - 1;    /* Try this ....from year 1 */
  275.  
  276. days = (y / 400) * 146097;    /* 400 year cycles */
  277.  
  278. y = y % 400;            /* Remainder    */
  279.  
  280. days += (y / 4) * 1461;        /* 4 year cycles */
  281.  
  282. days -= (y / 100);        /* These hundreds NOT leap years */
  283.  
  284. y %= 4;
  285.  
  286. /* The year immediately prior to the remainder was a leap year */
  287.  
  288. days += y * 365;    /* Therefore none of these is leap */
  289.  
  290.  
  291.  
  292. /* Now the number of days this year up to day, month, year    */
  293. /* If this year is leap year and it is later than February, add a day */
  294. days += MonthSum[month - 1] +
  295.     ( ((GLEAPYEAR(year)) ? 1 : 0 ) && (month > 2));
  296.  
  297. days += day;    /* Constant is 0 */
  298.  
  299. return(days % 7);
  300.  
  301. }
  302.  
  303. /********************************
  304.  * jCalculate(day,month,year)    *
  305.  * Calculate weekday for O.S.    *
  306.  ********************************/
  307.  
  308. ULONG jCalculate(day,month,year)
  309.  
  310. LONG    day, month, year;
  311.  
  312. {
  313. REGISTER ULONG    y, days;
  314.  
  315.  
  316. /* If this is the Julian calendar */
  317.  
  318.  
  319. /************************************************************************
  320.  * For the Julian calendar:-                        *
  321.  * y = year - 1 + 4     Start at 3BC - remainders then all non-leaps    *
  322.  * N = y / 4;        Number of 4 year cycles, add N * K2 to days    *
  323.  * R = y % 4;        Remainder                    *
  324.  * Now up to maximum of 3 more years                    *
  325.  * days += R * 365;                            *
  326.  * days += day + Constant;                        *
  327.  * This calendar repeats itself every 700 years.            *
  328.  ************************************************************************/
  329.  
  330.  
  331.  
  332. y = year + 3;
  333.  
  334. days =    (y / 4) * 1461 +            /* 4 year cycles    */
  335.     (y % 4) * 365 +                /* Years left over    */
  336.  
  337.     MonthSum[month - 1] +            /* Up to end of last m    */
  338. (((JLEAPYEAR(year)) && (month > 2)) ? 1 : 0) +    /* Leap after February    */
  339.     day;                     /* Constant is zero    */
  340.  
  341.  
  342.  
  343. return(days % 7);
  344.  
  345. }
  346.  
  347.  
  348.  
  349. /**************
  350. MainLoop:
  351. ***************/
  352.  
  353.  
  354. VOID main()
  355.  
  356. {
  357. LONG    day, month, year;
  358.  
  359. REGISTER ULONG    j,g;
  360.  
  361. FOREVER
  362.     {
  363.  
  364.  
  365.     printf("Date dd,mm,yyyy (0,0,0 to exit) >");
  366.     scanf("%ld,%ld,%ld", &day, &month, &year);
  367.  
  368.     if (day <= 0) return;
  369.  
  370.     if (jLegalDate(day,month,year))
  371.         j = jCalculate(day,month,year);
  372.     else
  373.         j = 7;
  374.  
  375.     if (gLegalDate(day,month,year))
  376.         g = gCalculate(day,month,year);
  377.     else
  378.         g = 7;
  379.  
  380.     printf("%s (O.S.)  %s (N.S.)\n\n", WeekDay[j], WeekDay[g]);
  381.  
  382.  
  383.     }
  384.  
  385. }
  386.  
  387.